#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <dirent.h>
#include <time.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <getopt.h>
#include <syslog.h>
#include "cJSON.h"
//#include "mosquitto_arg.h"
#include "mosquitto.h"
int g_stop = 0;


typedef struct mosquitto_s 
{
    char               *host;
    int                port;
    char               *topic;
    char               *client_id;
    char               *user;
    char               *password;
    int                keepalive;
    char               *recv_message;
    char               *send_message;
}mosquitto_t;	


char 		timechar[256]={0};


void sig_handle(int signum)
{
        if(SIGUSR1 == signum)
        {
                g_stop = 1;
        }
}
void print_usage(char *progname)
{
	printf("%s usage: \n",progname);
	printf("-H(--broker addr):specify Aliyun  address.\n");
	printf("-p(--port):specify server Aliyun port.\n");
	printf("-t(--topic): have publish power topic\n");
	printf("-d(--daemon):\n");
	printf("-c(--client_id): put Aliyun clinet id\n");
	printf("-u(--user): put Aliyun usr name\n");
	printf("-s(--passwd): put usr passwd\n");
	printf("-k(--keepalive): put keep time\n");
	printf("-h(--help): print this help information\n");
}


void sub_connect_callback(struct mosquitto *mosqut, void *obj, int rc);

void sub_message_callback(struct mosquitto *mosqut, void *obj, const struct mosquitto_message *msg);

int mosquitto_sub_start(struct mosquitto* mosqut,mosquitto_t* mosquittio);

int main(int argc,char **argv)
{
	int		daemon_run = 0;
	int		opt;
	int		rv = -1;
	mosquitto_t	mosq;

	struct mosquitto* mosqut;

	memset(&mosq,0,sizeof(mosq));

        struct option           opts[] = { 
                {"Host",required_argument,NULL,'H'},
                {"port",required_argument,NULL,'p'},
		{"topic",required_argument,NULL,'t'},
		{"daemon",no_argument,NULL,'d'},
		{"client_id",required_argument,NULL,'c'},
		{"user name",required_argument,NULL,'u'},
		{"Passwd",required_argument,NULL,'s'},
		{"keepalive",required_argument,NULL,'k'},
		{"help",no_argument,NULL,'h'},

                {NULL,0,NULL,0}
        };  

        while((opt = getopt_long(argc,argv,"H:p:t:dc:u:s:k:h",opts,NULL)) != -1) 
        {   
                switch(opt)
                {   
                        case 'H':
                                mosq.host = optarg;
                                break;
                        case 'p':
                                mosq.port = atoi(optarg);
                                break;
                        case 't':
                                mosq.topic = optarg;
				break;
			case 'd':
				daemon_run = 1;
				break;
			case 'c':
				mosq.client_id = optarg;
				break;
			case 'u':
				mosq.user = optarg;
				break;
			case 's':
				mosq.password = optarg;
				break;
			case 'k':
				mosq.keepalive = atoi(optarg);
				break;
			case 'h':
				print_usage(argv[0]);
				return 0;
					
	
                }   
        }

	mosq.send_message = NULL;
	mosq.recv_message = NULL;


	if (mosq.host == NULL||!mosq.port||mosq.topic == NULL||mosq.client_id == NULL||\
	  mosq.user == NULL||mosq.password == NULL||!mosq.keepalive )
	{
		print_usage(argv[0]);

		return 0;
	}
	if(daemon_run)
	{
		daemon(0,0);
	}
	signal(SIGUSR1,sig_handle);
	rv = mosquitto_sub_start(mosqut,&mosq);

	
	
	return 0;	

}



int mosquitto_sub_start(struct mosquitto* mosqut,mosquitto_t *mosq)
{
	int rv = -1;
	rv =  mosquitto_lib_init();
	
	if(rv != MOSQ_ERR_SUCCESS )
	{
		printf("Init mosquitto lib failure: %s\n",strerror(errno));
		goto cleanup;
	}
	
	mosqut = mosquitto_new(mosq->client_id,false,(void*)mosq);
	if(!mosqut)
	{
		printf("Creat mosquitto client failure: %s\n",strerror(errno));
		goto cleanup;
	}

	printf("Creat mosquitto client success\n");
	

	mosquitto_connect_callback_set(mosqut,sub_connect_callback);

	if(mosquitto_username_pw_set(mosqut,mosq->user,mosq->password))
	{
		printf("mosquitto username and passwd failure: %s\n",strerror(errno));
		goto cleanup;
	}
		

	while(!g_stop)
	{
		rv = mosquitto_connect(mosqut,mosq->host,mosq->port,mosq->keepalive);

		if(rv != MOSQ_ERR_SUCCESS)
		{
			printf("Client connnect to Server failure: %s\n",strerror(errno));
			continue;
			sleep(1);
		}

		printf("Connect to Aliyun success\n");
	
		rv = mosquitto_loop_forever(mosqut,-1,1);

		sleep(40);



		if(rv!=MOSQ_ERR_SUCCESS)
		{
			printf("%s\n",strerror(errno));
			goto cleanup;
		}
		printf("MOS_sub_start success\n");	
	}


	printf("sub_close\n");
	return 0;

cleanup:
	printf("sub_satrt failure!!\n");

	mosquitto_destroy(mosqut);
	mosquitto_lib_cleanup();
	return 0;

	

}

void sub_connect_callback(struct mosquitto *mosqut, void *obj, int rc)
{
	mosquitto_t	*mosq;
	mosq = (mosquitto_t*)obj;
	int mid;
	printf("this is sub_connect_callback\n");


	if(rc==0)
	{
		if(mosquitto_subscribe(mosqut,&mid,mosq->topic,0)!=MOSQ_ERR_SUCCESS)
		{
			printf("Mosquitto Sub failure: %s\n",strerror(errno));
			return;
		}	


		printf("Mosquitto Sub success,SUB_TOPIC:%s\n",mosq->topic);

		printf(" rc:%d\n",rc);
	}	
	mosquitto_message_callback_set(mosqut,sub_message_callback);

		
}

void sub_message_callback(struct mosquitto *mosqut, void *obj, const struct mosquitto_message *msg)
{
	printf("This is msg callback\n");


	mosquitto_t     *mosq;
	mosq = (mosquitto_t*)obj;
	printf("THIS is msg callback\n");
	memcpy(mosq-> recv_message, (char *)msg->payload, strlen((char *)msg->payload));
    	printf("recv_message: %s\n", mosq->recv_message);
 
        mosquitto_disconnect(mosqut);
}
